/**
 * 
 */
package boundary.components;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.Ellipse2D;

import calculator.CoordinateManager;

/**
 * @author davide
 *
 */
public class SmartPolygon extends Polygon
{
    private static final long serialVersionUID = -357286528916303603L;
    
    Point cursor;
    boolean isClosed = false;
    boolean isValidCursorLocation = false;
    
    public SmartPolygon()
    {
	super();
	this.cursor = new Point();
    }
    
    public void setCursorLocation(int x, int y, int zoomFactor)
    {
	this.cursor.setLocation(CoordinateManager.absoluteCoord(x, zoomFactor),
		CoordinateManager.absoluteCoord(y, zoomFactor));
	
	this.isValidCursorLocation = true;
    }
    
    public void resetCursorLocation()
    {
	this.isValidCursorLocation = false;
    }
    
    public boolean addPoint(int arg0, int arg1, int zoomFactor)
    {
	int xCoord = CoordinateManager.absoluteCoord(arg0, zoomFactor);
	int yCoord = CoordinateManager.absoluteCoord(arg1, zoomFactor);
	
	if(this.isClosing(xCoord, yCoord) == true) {
	    this.isClosed = true;
	    return true;
	}
	
	super.addPoint(xCoord, yCoord);
	return false;
    }
    
    @Override
    public void reset()
    {
	super.reset();
	this.isClosed = false;
    }
    
    private boolean isClosing(int x, int y)
    {
	Ellipse2D area;
	int radius = 10;
	
	if(this.npoints == 0) {
	    return false;
	}
	
	area = new Ellipse2D.Double(this.xpoints[0] - radius, this.ypoints[0] - radius, 2 * radius, 2 * radius);
	return area.contains(x, y);
    }
    
    public boolean isClosing(int x, int y, int zoomFactor)
    {
	return this.isClosing(CoordinateManager.absoluteCoord(x, zoomFactor),
		CoordinateManager.absoluteCoord(y, zoomFactor));
    }
    
    public boolean isClosed()
    {
	return this.isClosed;
    }

    private void paintAsPolyLine(Graphics2D g, int zoomFactor)
    {
	float dash[] = { 5.0f };
	
	g.setColor(new Color(0, 0, 255));
	g.setStroke(new BasicStroke(1.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, dash, 0.0f));
	
	for(int i = 1; i < this.npoints; ++i)
	{
	    g.drawLine(CoordinateManager.relativeCoord(this.xpoints[i -1], zoomFactor),
		    CoordinateManager.relativeCoord(this.ypoints[i -1], zoomFactor),
		    CoordinateManager.relativeCoord(this.xpoints[i], zoomFactor),
		    CoordinateManager.relativeCoord(this.ypoints[i], zoomFactor));
	}
	
	if(this.npoints > 0 && this.isValidCursorLocation == true) {
	    g.drawLine(CoordinateManager.relativeCoord(this.xpoints[this.npoints -1], zoomFactor),
		    CoordinateManager.relativeCoord(this.ypoints[this.npoints-1], zoomFactor),
		    CoordinateManager.relativeCoord(this.cursor.x, zoomFactor),
		    CoordinateManager.relativeCoord(this.cursor.y, zoomFactor));
	}
    }
    
    private void paintAsPolygon(Graphics2D g, int zoomFactor)
    {
	Polygon viewPort = new Polygon();
	
	g.setStroke(new BasicStroke(2));
	g.setColor(new Color(255, 255, 0));
	
	for(int i = 0; i < this.npoints; ++i)
	{
	    viewPort.addPoint(CoordinateManager.relativeCoord(this.xpoints[i], zoomFactor),
		    CoordinateManager.relativeCoord(this.ypoints[i], zoomFactor));
	}
	
	g.drawPolygon(viewPort);
    }
    
    public void paintComponent(Graphics2D g, int zoomFactor)
    {
	if(this.isClosed) {
	    this.paintAsPolygon(g, zoomFactor);
	}
	
	else {
	    this.paintAsPolyLine(g, zoomFactor);
	}
    }
}
